home *** CD-ROM | disk | FTP | other *** search
- From: mrob@world.std.com (Robert P Munafo)
- Subject: "Missile" source from 1984
-
- Recently in comp.sys.mac.programmer there has been some
- discussion of early Macintosh programs that still run on current
- machines, and my Missile Command game from mid-1984 was mentioned.
-
- This program was written in Lisa Pascal, the cross-development
- system that everyone had to use until Stanford's sumacc came along,
- and has the rather charming property of continuing to run on all
- new machines that Apple comes out with. I ran it on my own
- Power Mac 6100/60 yesterday just for fun. It's just as playable
- as it was on the old 128K Mac (although the timing for the "Game
- Over" screen is now way off, as I didn't check TickCount for
- that).
-
- I have not done anything to this code, like try to port it to
- any recent Pascal compiler or anything like that. I know that
- Lisa Pascal, Macintosh Pascal, and TML Language Systems Pascal
- were all reasonably compatible with each other; after that I
- switched over to Think C and lost track.
-
- The "%title" and "%subtitle" directives were for the print spooler
- on the Dartmouth mainframe that I used to print out listings.
-
- There seem to be a lot more options in the Game Options dialog
- than the actual Missile game provides. I'm not sure what's going
- on with that.
- ----------- Cut Here --- Pascal Source code -----------
-
-
- { %title 'Missile - a game for the Apple Macintosh.' }
- { %subtitle 'Overall program description.' }
- { $X- } { Turns off A.R.S.E. }
-
- PROGRAM Game;
- {
- Missile -- A Missile Command game for the Macintosh
- by Robert P. Munafo at Dartmouth College.
-
- I wrote this to learn a bit about Mac programming. It has a
- few 'standard user interface' bugs:
-
- It doesn't update the window during the 'End of round X' and
- 'GAME OVER' routines. (It only updates while playing.)
- It won't quit when you select "quit" while a desk accessory is
- on screen. Instead, it will wait until you close all the
- desk accessories, then quit.
- The cursor looks the same all the time. It should change
- shape to let the user know when he can and cannot fire missiles.
-
- It also has some missing features (which I hope to add soon):
-
- o Smart Bombs
- o Add an "Ammunition: [xxx]% of normal" item to the dialog box.
- o Sound
- o User should be able to pick what round the game starts with
- o High scores list saved on the disk
- o Two-player option
- o The animation needs to be made faster (in some manner)
- }
-
- { %subtitle 'USES statements' }
- USES {$U Obj/QuickDraw } QuickDraw,
- {$U Obj/OSIntf } OSIntf,
- {$U Obj/ToolIntf } ToolIntf,
- {$U Obj/PackIntf } Packintf;
-
- { %subtitle 'Constants' }
- CONST lastMenu = 4; { number of menus }
- appleMenu = 1; { menu ID for desk accessory menu }
- fileMenu = 256; { menu ID for File menu }
- EditMenu = 257; { menu ID for the Edit menu. }
- GameMenu = 258; { menu ID for Game menu }
- str_1_ID = 300; {ID for my first string of text}
- str_2_ID = 350; {ID for my second string of text}
- box_ID = 450; {ID of "about" dialog box}
- box2_id = 451; {ID of options box}
-
- fbIdle = 0;
- fbGrow = 1;
- fbShrink = 2;
- maxfb = 60; { Maximum number of fireballs allowed. }
- fbRad = 15; { Radius of fireballs. }
- fbRadRate = 2; { Rate of expansion/contraction of fireballs. }
- msIdle = 0;
- msActive = 1;
- msNormal = 1;
- msMirv = 2;
- msSmart = 3;
- maxms = 20; { Maximum number of missiles allowed. }
- mWidth = 3; { Width of missile tracks. }
- CityHeight = 40; { Distance from bottom up to cities. }
- CityWidth = 50; { Width of cities. }
- BuildHeight = 30; { Maximum height of buildings. }
- BuildWidth = 4; { Width of buildings. }
- nCities = 6; { Number of cities. }
-
- TYPE fireball = RECORD { Data type to describe a fireball. }
- bounds: Rect; { Rectanggle to copy bits into. }
- size: INTEGER; { Current radius of fireball. }
- mode: INTEGER; { Idle, Growing, or shrinking. }
- END;
-
- missile = RECORD { Data type to describe a missile. }
- start: Point; { One endpoint of the missile's path. }
- pos: Point; { Position within path - 0 to 1. }
- dh, dv: INTEGER; { Vertical and horizontal speed in pixels. }
- city: INTEGER; { Number of the target city. }
- kind: INTEGER; { MIRV or normal. }
- mode: INTEGER; { Idle or Active. }
- END;
-
- VAR myMenus: ARRAY [1..lastMenu] OF MenuHandle;
- screenRect: Rect;
- doneFlag: BOOLEAN;
- myEvent: EventRecord;
- code, refNum: INTEGER;
- wRecord: WindowRecord;
- myWindow, whichWindow: WindowPtr;
- first_string, second_string : StringHandle; { Handles to strings of text for AboutMissile. }
-
- { My game variables are here. }
- fbBitMap: BitMap; { BitMap for fireball pictures. }
- fbBits: ARRAY[1..3600] OF INTEGER; { Actual bits for fireball pictures. }
-
- crosshairs: Cursor; { Crosshairs cursor read in from resource. }
- hCurs: CursHandle; { Handle to the cursor. }
- CityPattern: PatHandle;{ Handle to pattern in which to draw cities. }
- FieldWidth: INTEGER; { Width of the playing field. }
- FieldHeight: INTEGER; { Height of the playing field. }
- i: INTEGER; { Loop variable. }
- fbs: ARRAY [1..maxfb] OF fireball; { Each entry describes one fireball. }
- missiles: ARRAY [1..maxms] OF missile; { Each entry describes one missile. }
- nMissiles: INTEGER; { Number of currently active missiles. }
- lastTick: LONGINT; { System clock at time of previous update. }
- gameOver: BOOLEAN; { Set true when all cities are destroyed. }
- PauseFlag: BOOLEAN; { True when game is being paused. }
- Playing: BOOLEAN; { True except buring bonus points and GAME OVER screens. }
- esFlag: BOOLEAN; { True if "GAME OVER" is to be drawn after exiting main loop. }
- enddelay: INTEGER; { Used to wait a while after end of round. }
- citiesLeft: INTEGER; { Number of cities still alive. }
- bcities: INTEGER; { Number of bonus cities they have left. }
- cities: ARRAY [1..nCities] OF BOOLEAN; { State of each city : false = destroyed. }
- cities2: ARRAY [1..nCities] OF BOOLEAN; { State of the city before the round began. }
- nukeHeight: INTEGER; { Vertical position of fireball required to destroy city. }
- endv: INTEGER; { Y-coordinate of the end of a missile's path. }
- MirvRate: INTEGER;
- mirvHeight: INTEGER; { Height at which Mirvs MIRV. }
- mirvNasty: INTEGER; { Percent chance of sub-missile on mirv for each city. }
- msSpeed: INTEGER; { Vertical speed of missiles, in 1/16ths of a pixel.}
- msRate: INTEGER; { Percent rate of missile production. }
- RoundNumber: INTEGER; { Number of the current round. }
- Score: LONGINT; { The player's current score. }
- DisScore: LONGINT; { Score currently displayed on the screen. }
- HighScore: LONGINT; { The current highest score. }
- RoundH: INTEGER;
- Scoreh: INTEGER; { Horiz. position of text 'Score:' }
- ScoreNumH: INTEGER; { Horiz. position of score. }
- statsH: INTEGER; { Horiz. position of text 'Enemy left:' }
- statsNumH: INTEGER;
- statsRect: Rect;
- eLeft: INTEGER; { How many enemy missiles are left this round. }
- yLeft: INTEGER; { How many missiles you (the player) have left. }
- eDestroyed: INTEGER; { Number of enemy missiles destroyed. }
- eDesH: INTEGER; { Horiz. position of text 'Enemy Destroyed:' }
- eDesNumH: INTEGER; { Horiz. position of # of enemy missiles destroyed. }
-
- gameSpeed: INTEGER; { Number of ticks between each AdvanFb call. }
- StartRound: INTEGER; { Round to start off with. }
- mFlag1: BOOLEAN; { Do missiles aim for dead cities? }
- MFlag2: INTEGER; { Extent to which enemy missiles blow up. }
- MExists: ARRAY[1..3] OF BOOLEAN; { Does this type of missile occur? }
- MPBase: ARRAY[1..3] OF INTEGER; { Value of missile at first round... }
- MPExtra: ARRAY[1..3] OF INTEGER; { ...plus this much each additional round... }
- MPoints: ARRAY[1..3] OF INTEGER; { ...is this much in all. }
-
- { %subtitle 'Init routine for menus.' }
- PROCEDURE SetUpMenus;
- VAR i: INTEGER;
- BEGIN
- myMenus[1] := GetMenu(appleMenu); { Load menu from disk. }
- MyMenus[1]^^.MenuData[1] := Chr(AppleSymbol); { Change title to the Apple symbol. }
- AddResMenu(myMenus[1],'DRVR'); { Add items for desk accessories. }
- myMenus[2] := GetMenu(fileMenu);
- myMenus[3] := GetMenu(editMenu);
- myMenus[4] := GetMenu(GameMenu);
- FOR i:=1 TO lastMenu DO
- InsertMenu(myMenus[i],0);
- DrawMenuBar;
- END; { of SetUpMenus }
-
- { %subtitle 'Init routine for fireball BitMaps.' }
- { This routine is called by the main Init routine, below. It creates a
- bunch of bit images of circles off-screen, which can later be drawn on
- the screen much faster than FrameOval. }
- PROCEDURE InitFbs;
- VAR i: FIXED;
- aRect: Rect; { Rectangle for drawing FrameOvals. }
- saveBits: BitMap; { To save the current GrafPort while drawing off-screen. }
- SaveRect: Rect;
- BEGIN
- SaveBits := ThePort^.PortBits;
- SaveRect := ThePort^.PortRect;
- fbBitMap.rowBytes := 8;
- SetRect(fbBitMap.bounds, 0, 0, 60, 60);
- ThePort^.portRect := fbBitMap.Bounds;
-
- PenSize(fbRadRate,fbRadRate);
- PenPat(black);
- PenMode(PatCopy);
- SetRect(aRect, 30, 30, 30, 30); { Start with an empty rectangle in the center. }
- FOR i := 0 TO 14 DO BEGIN
- fbBitMap.baseAddr := @fbBits[240*i + 1]; { Pick starting address for this picture. }
- insetRect(aRect, -2, -2); { Make rect a bit larger. }
- SetPortBits(fbBitMap);
- EraseRect(thePort^.portBits.bounds); { Erase to all white. }
- FrameOval(aRect); { Draw the circle. }
- END;
- SetPortBits(SaveBits); { Return to normal screen drawing. }
- ThePort^.PortRect := SaveRect;
- END; { of InitFbs }
-
- { %subtitle 'Init routine' }
- PROCEDURE Setup;
- VAR wRect: Rect; { Window Rectangle. }
- i: INTEGER;
- BEGIN
- { Macintosh System initialization. }
- InitGraf(@thePort); { Quickdraw. }
- InitFonts; { Font Manager. }
- InitWindows; { Window Manager. }
- InitMenus; { Menu Manager. }
- TEInit; { TextEdit. }
- InitDialogs(NIL); { Dialog manager. }
- InitCursor; { Cursor handler. }
- InitAllPacks; { Package Manager. }
-
- SetUpMenus; { My routine to insert the menus. }
- hCurs := POINTER(GetCursor(256)); { Load the Crosshairs cursor that I use in the game. }
- crosshairs := hCurs^^;
- SetCursor(crosshairs);
- CityPattern := GetPattern(256);
-
- screenRect := screenBits.bounds; { Don't actually use this, but might later. }
-
- doneFlag := FALSE; { This flag is set to False when user selects 'Quit'. }
- HighScore := 0;
-
- GameSpeed := 8; { Set up all the user-settable options. }
- StartRound := 1;
- MFlag1 := True;
- MFlag2 := 1;
- FOR i := 1 TO 3 DO BEGIN
- MExists[i] := True;
- MPBase[i] := 10*i;
- MPExtra[i] := 10*i;
- END;
-
- { myWindow := GetNewWindow(256, @wRecord, POINTER(-1)); }
- wRect := ScreenRect;
- wRect.top := 20;
- myWindow := NewWindow(@wRecord,
- wRect, { BoundsRect }
- 'Missile Command by Robert Munafo',
- True, { Visible }
- 0, { ProcID }
- POINTER(-1), { behind }
- False, { GoAwayFlag }
- 0); { RefCon }
- SetPort(myWindow); { Might as well play the game in a window... }
-
- FieldWidth := MyWindow^.portRect.right; { These variables are used by the game. }
- FieldHeight := MyWindow^.portRect.bottom;
-
- TextFont(0);
- TextFace([]);
-
- InitFbs; { Set up the fireball BitMaps. }
-
- second_string := GetString(str_2_ID); { Get strings from resource. }
- first_string := GetString(str_1_ID);
-
- FlushEvents(everyEvent,0);
- END;
-
- { %Subtitle 'Gets a text string' }
-
- { This routine conducts a dialog to get a text string from the
- user. The function value returned indicates whether the user stopped by entering
- OK or cancel. The ID is the dialog ID number to use and Text is the
- text they typed in. To get the text, we display the dialog window,
- get the handle of the edit text and execute a small event loop wich waits
- until one of the two buttons is pressed. When done, we dispose of the dialogue
- window, set the flag depending on the means of exiting and return the text.
- The predefined dialogue window has the following items in it:
-
- Item Number Item
- 1 OK button, Enabled
- 2 Cancel button, Enabled
- 3 EditText area, Enabled
- 4 StatText area, Disabled (Prompt)
- 5... Anything else, Disabled
- *)
-
- { the actual function has been deleted. }
-
- { %subtitle '"About Missile" routine.' }
- { This routine is nearly identical to Jason Ansley's About_Windows routine. }
- PROCEDURE AboutMissile;
- VAR item_chosen : integer; {which botton was hit (I only have one so it doesn't really matter)}
- item_type : integer; {type of item in res. def. file (needed to pass as parameter)}
- first_handle, second_handle : Handle; {handles to my items}
- the_dialog : DialogPtr; {a pointer to my dialog box}
- box : rect; {the display rectangle of the item}
-
- BEGIN
- the_dialog := GetNewDialog(box_ID, NIL, pointer(-1)); {get dialog box from resource file}
-
- GetDItem(the_dialog, 2, item_type, first_handle, box); {get text format info from file}
- GetDItem(the_dialog, 3, item_type, second_handle, box);
-
- SetIText(first_handle, first_string^^); {set the lines of text into the box}
- SetIText(second_handle, second_string^^);
-
- ModalDialog(NIL, item_chosen); {operate the box}
- DisposDialog(the_dialog); {get rid of the box now that I'm done with it}
- END;
-
- { %subtitle 'My own random number routine.' }
- FUNCTION Rnd (n: FIXED) : FIXED; { Function to generate a random integer from
- 1 to N. }
- BEGIN
- Rnd := (ABS(Random) MOD n) + 1;
- END;
-
- { %subtitle 'DrawNumber - converts number to string and draws it on the screen.' }
- PROCEDURE DrawNumber (n: LONGINT);
- VAR s: Str255;
- BEGIN
- NumToString(n, s);
- DrawString(s);
- END;
-
- { %subtitle 'Update the score at the bottom of the screen.' }
- PROCEDURE UpdScore;
- BEGIN
- TextMode(SrcBic);
- MoveTo(ScoreNumH, FieldHeight-5);
- TextSize(24);
- DrawNumber(disScore);
-
- TextMode(SrcOr);
- MoveTo(ScoreNumH, FieldHeight-5);
- DrawNumber(Score);
- disScore := Score;
-
- EraseRect(statsRect);
- TextMode(SrcOr);
- MoveTo(statsNumH, FieldHeight-20);
- TextSize(12);
- DrawNumber(eLeft);
- MoveTo(statsNumH, FieldHeight-5);
- DrawNumber(yLeft);
- TextMode(SrcCopy);
- MoveTo(eDesNumH, FieldHeight-20);
- DrawNumber(eDestroyed);
- END;
-
- { %subtitle 'Print the score.' }
- PROCEDURE DrawScore;
- BEGIN
- TextMode(srcCopy);
- MoveTo(ScoreH, FieldHeight-14);
- TextSize(12);
- DrawString('Score: ');
- MoveTo(ScoreNumH, FieldHeight-5);
- TextSize(24);
- DrawNumber(Score);
- disScore := Score;
-
- TextSize(12);
- MoveTo(statsH, FIeldHeight-20);
- DrawString('Enemy left: ');
- DrawNumber(eLeft);
- MoveTo(statsH, FieldHeight-5);
- DrawString('Yours left: ');
- MoveTo(statsNumH, FieldHeight-5);
- DrawNumber(yLeft);
- MoveTo(eDesH, FieldHeight-20);
- DrawString('Destroyed: ');
- MoveTo(eDesNumH, FieldHeight-20);
- DrawNumber(eDestroyed);
- END;
-
- { %subtitle 'Print round #, score, and # killed.' }
- PROCEDURE BottomLine;
- BEGIN;
- TextSize(12);
- RoundH := 10 + StringWidth('Round: ');
- ScoreH := RoundH + 2*StringWidth('00 ');
- ScoreNumH := ScoreH + StringWidth('Score: ');
- eDesH := FieldWidth - StringWidth('Destroyed: 0000 ');
- eDesNumH := FieldWidth - StringWidth('0000 ');
- statsH := eDesH - StringWidth('Enemy left: 000 ');
- statsNumH := eDesH - StringWidth('000 ');
- SetRect(statsRect, statsNumH, FieldHeight-30, eDesH-2, FieldHeight);
-
- TextMode(srcCopy);
- MoveTo(10, FieldHeight-14);
- DrawString('Round: ');
- MoveTo(RoundH, FieldHeight-5);
- TextSize(24);
- DrawNumber(RoundNumber);
-
- DrawScore;
- MoveTo(eDesH, FieldHeight-5);
- DrawString('High Score: ');
- DrawNumber(HighScore);
- END;
-
- { %subtitle 'Create a new fireball.' }
- PROCEDURE AllocFb (location: Point);
- VAR i: INTEGER;
- idlefb: INTEGER;
- BEGIN
- idlefb := 0;
- FOR i := 1 TO maxfb DO
- IF (fbs[i].mode = fbIdle) AND (idlefb = 0)
- THEN idlefb := i;
- IF idlefb <> 0
- THEN BEGIN
- SetRect(fbs[idlefb].bounds, location.h-30, location.v-30, location.h+30, location.v+30);
- fbs[idlefb].size := 0;
- fbs[idlefb].mode := fbGrow;
- END;
- END; { of AllocFb }
-
- { %subtitle 'Advance (animate) the fireballs.' }
- PROCEDURE AdvanFb;
- VAR i: INTEGER;
- aRect: Rect;
- fbrect: Rect; { Rectangle for drawing fireballs. }
- BEGIN
- PenSize(fbRadRate,fbRadRate);
- PenPat(black);
- SetRect(aRect, 0, 0, 60, 60);
- FOR i := 1 TO maxfb DO BEGIN
- IF fbs[i].mode <> fbidle
- THEN
- CASE fbs[i].mode OF
-
- fbGrow: BEGIN
- fbs[i].size := fbs[i].size + 1;
- fbBitMap.baseAddr := @fbBits[240*fbs[i].size - 239]; { Select a fireball picture. }
- CopyBits(fbBitMap, thePort^.PortBits, aRect, fbs[i].bounds, SrcOr, NIL);
-
- IF fbs[i].size >= fbRad
- THEN fbs[i].mode := fbShrink;
- END;
-
- fbShrink: BEGIN
- fbBitMap.baseAddr := @fbBits[240*fbs[i].size - 239]; { Select the correct fireball picture. }
- CopyBits(fbBitMap, thePort^.PortBits, aRect, fbs[i].bounds, SrcBic, NIL);
-
- fbs[i].size := fbs[i].size - 1;
- IF fbs[i].size = 0
- THEN fbs[i].mode := fbIdle;
- END;
-
- END; { of mode case }
- END; { of loop }
- END; { of AdvanFb }
-
- { %subtitle 'Create a new enemy missile.' }
- PROCEDURE AllocMs(position: Point; city: INTEGER; kind: INTEGER);
- VAR i: INTEGER;
- idleMs: INTEGER;
- targetcity: integer;
- targeth: integer;
- BEGIN
- idlems := 0;
- FOR i := 1 TO maxMs DO
- IF (missiles[i].mode = msIdle) AND (idlems = 0)
- THEN idlems := i;
- IF idlems <> 0
- THEN BEGIN
- i := idlems;
- missiles[i].start.v := position.v; { Set coordinates for beginning of path. }
- missiles[i].start.h := position.h;
- missiles[i].pos.v := missiles[i].start.v * 16; { Initial current position is }
- missiles[i].pos.h := missiles[i].start.h * 16; { at start of path.o}
- missiles[i].dv := msSpeed; { Speed of missile. }
-
- missiles[i].city := city;
- targeth := (((missiles[i].city*2 - 1)*FieldWidth) DIV (2*nCities))*16;
- missiles[i].dh := (targeth-(missiles[i].start.h*16)) DIV
- (((endv-missiles[i].start.v)*16) DIV missiles[i].dv);
- missiles[i].kind := kind;
- missiles[i].mode := msActive;
- nMissiles := nMissiles + 1;
- END;
- END;
-
-
- FUNCTION BlackPixel(aPoint: Point) : BOOLEAN;
- BEGIN
- aPoint.h := aPoint.h DIV 16;
- aPoint.v := aPoint.v DIV 16;
- BlackPixel := (GetPixel(aPoint.h, aPoint.v)
- AND GetPixel(aPoint.h+1, aPoint.v));
- END;
-
- { %subtitle 'Advance (animate) the enemy missiles.' }
- PROCEDURE AdvanMs;
- VAR i, j: INTEGER;
- newpos, newpixel: Point;
- detonate: BOOLEAN;
- Points: INTEGER;
- BEGIN
- penMode(PatCopy);
- FOR i := 1 TO maxms DO BEGIN
- IF missiles[i].mode <> msIdle
- THEN BEGIN
- newpos.v := missiles[i].pos.v + missiles[i].dv;
- newpos.h := missiles[i].pos.h + missiles[i].dh;
- newpixel.v := newpos.v DIV 16;
- newpixel.h := newpos.h DIV 16;
-
- detonate := FALSE;
- IF BlackPixel(newpos) OR BlackPixel(missiles[i].pos)
- THEN detonate := TRUE;
-
- PenSize(mWidth, mWidth);
- PenPat(gray);
- MoveTo(missiles[i].pos.h DIV 16, missiles[i].pos.v DIV 16);
- LineTo(newpixel.h, newpixel.v);
- missiles[i].pos := newpos;
-
- IF (missiles[i].kind = msMirv) { If it's a Mirv, }
- AND (newpixel.v > mirvHeight) { and it's reached the right altitude, }
- THEN BEGIN { then make lots of little missiles... }
- FOR j := 1 TO nCities DO
- IF (j <> missiles[i].city) AND (Rnd(100) < mirvNasty)
- THEN allocMs(newpixel, j, msNormal);
- missiles[i].kind := msNormal;
- END;
-
- IF (newpos.v DIV 16 >= endv) { If the missile has reached its target }
- OR detonate { or hit a fireball, }
- THEN BEGIN
- PenSize(mWidth+2, mWidth+2);
- PenPat(white);
- MoveTo(missiles[i].start.h-1, missiles[i].start.v-1); { Erase the line. }
- LineTo(newpixel.h-1, newpixel.v-1);
-
- missiles[i].mode := msIdle; { turn off the missile, }
- nMissiles := nMissiles-1;
-
- IF detonate THEN BEGIN
- IF (MFlag2 = 2) OR ((MFlag2 = 1) AND (Rnd(25) > RoundNumber))
- THEN allocFb(newpixel); { Make a new fireball. }
- eDestroyed := eDestroyed + 1;
- Score := Score + MPoints[missiles[i].kind];
- UpdScore;
- END
- ELSE
- IF cities[missiles[i].city]
- THEN BEGIN
- allocfb(newpixel);
- cities[missiles[i].city] := false;
- citiesLeft := citiesLeft - 1;
- IF citiesLeft+bCities = 0
- THEN gameOver := true;
- END;
- END; { Of detonate routine. }
- END; { Of THEN clause for this active missile. }
-
- END; { of missile loop }
- END; { of AdvanMs }
-
- { %subtitle 'Print a string in the center of the window.' }
- PROCEDURE Centre (TheText: Str255; posV: INTEGER);
- BEGIN
- MoveTo((FieldWidth-StringWidth(TheText))DIV 2, posV);
- DrawString(TheText);
- END;
-
- { %subtitle 'Clear the screen.' }
- PROCEDURE ClearScreen;
- VAR aRect: Rect;
- BEGIN
- aRect.top := 0;
- aRect.left := 0;
- aRect.bottom := FieldHeight;
- aRect.right := FieldWidth;
- FillRect(aRect, White);
- END;
-
- { %subtitle 'Draw a city.' }
- PROCEDURE DrawCity (city: INTEGER);
- VAR CityLoc: Point;
- bOffset: INTEGER;
- aRect: Rect;
- BEGIN;
- RandSeed := 2; { Make each city look the same. }
- cityloc.v := FieldHeight - CityHeight;
- cityloc.h := ((city*2-1) * FieldWidth) DIV (2*nCities);
- bOffset := -(CityWidth DIV 2);
- WHILE bOffset<(CityWidth DIV 2) DO BEGIN
- aRect.left := cityloc.h + bOffset;
- aRect.top := cityloc.v - Rnd(BuildHeight);
- aRect.bottom := cityloc.v + 2;
- aRect.right := aRect.left + BuildWidth;
- FillRect(aRect, CityPattern^^);
- bOffset := bOffset + BuildWidth;
- END;
- END;
-
- { %subtitle 'Draw cities and bottom line.' }
- PROCEDURE DrawStuff;
- VAR i: INTEGER;
- aRect: Rect;
- BEGIN
- ClearScreen;
-
- FOR i := 1 TO nCities DO
- IF cities[i] THEN DrawCity(i);
- PenPat(Black);
- RandSeed := TickCount; { Randomize }
-
- BottomLine;
- END; { of DrawStuff }
-
- { %subtitle 'MinMax - Convert Num to String with range checking. }
- FUNCTION MinMax(TheString: Str255; minimum: INTEGER; Maximum: INTEGER) : INTEGER;
- VAR
- TheNumber: LONGINT;
- BEGIN
- StringToNum(TheString, TheNumber);
- IF TheNumber<Minimum THEN TheNumber := Minimum;
- IF TheNumber>Maximum THEN TheNumber := Maximum;
- MinMax := TheNumber;
- END;
-
- { %subtitle 'DoGameOptions - Does the big dialog box.' }
- Procedure DoGameOptions;
- CONST { Here are all the magic constants that go with that monster dialog box: }
- OK = 1; { OK button }
- GSpeed = 5; { Game Speed text box }
- SRound = 7; { Start Round text box }
- MPB = 18; { MPBase text boxes }
- MPE = 24; { MPExtra text boxes }
- MF1 = 8; { MFlag1 check box }
- MF2 = 10; { MFlag2 radio buttons }
- MEX = 15; { MExists check boxes }
-
- VAR savePort:grafptr; { For saving the GrafPort and restoring later. }
- DStorage: DialogRecord; { Storage for my dialog box. }
- DPtr: DialogPtr; { Pointer to my dialog box. }
- ItemHit: integer; { Item that was just hit by the user. }
- TheType: integer; { not used }
- TheHandle: Handle; { Temp. handle }
- TheRect: Rect; { not used. }
- TheString: str255; { Temp. string }
- TheValue: INTEGER; { Temp. integer value. }
- i: INTEGER; { Loop Variable. }
- Station: INTEGER; { Current setting of radio buttons. }
- BEGIN
- DPtr := getNewDialog(box2_id, @DStorage, pointer(-1)); { Load the data from disk . . . }
-
- GetDItem(Dptr, GSpeed, theType, theHandle, theRect); { Set up all the EditText boxes }
- NumToString(GameSpeed, TheString);
- SetIText(theHandle, TheString);
- GetDItem(Dptr, SRound, theType, theHandle, theRect);
- NumToString(StartRound, TheString);
- SetIText(theHandle, TheString);
-
- FOR i := 0 TO 2 DO BEGIN
- GetDItem(Dptr, MPB+i, theType, theHandle, theRect); { Text for points each missile is worth. }
- NumToString(MPBase[i+1], TheString);
- SetIText(theHandle, TheString);
- GetDItem(Dptr, MPB+3+i, theType, theHandle, theRect); { Text for plus sign. }
- TheString := '+';
- SetIText(theHandle, TheString);
- GetDItem(Dptr, MPE+i, theType, theHandle, theRect); { Text for additional points each round }
- NumToString(MPExtra[i+1], TheString);
- SetIText(theHandle, TheString);
- GetDItem(Dptr, MPE+3+i, theType, theHandle, theRect); { text : '* round' }
- TheString := '* round';
- SetIText(theHandle, TheString);
- GetDItem(Dptr, MEX+i, theType, theHandle, theRect); { Check boxes for types of missiles }
- TheValue := 0;
- IF MExists[i+1] THEN TheValue := 1;
- SetCtlValue(TheHandle, TheValue);
- END;
-
- FOR i := 0 to 2 DO BEGIN { Program the radio buttons. }
- GetDItem(Dptr, MF2+i, theType, theHandle, theRect);
- TheValue := 0;
- IF MFlag2 = i THEN TheValue := 1;
- SetCtlValue(Pointer(TheHandle), TheValue);
- END;
- Station := MF2 + MFlag2;
-
- GetDItem(Dptr, MF1, theType, theHandle, theRect); { Set check box for MFlag1. }
- TheValue := 0;
- IF MFlag1 THEN TheValue := 1;
- SetCtlValue(Pointer(TheHandle), TheValue);
-
- SelIText(DPtr, sRound, 0, 1000); { Initial selection is StartRound. }
-
- REPEAT
- ModalDialog(NIL, ItemHit); { Let them hit an item... }
-
- IF ItemHit IN [10,11,12] { Was it one of the radio buttons? }
- THEN BEGIN
- GetDItem(Dptr, Station, theType, theHandle, theRect); { Get the old one, and turn it off. }
- SetCtlValue(Pointer(TheHandle), 0);
- Station := ItemHit;
- GetDItem(Dptr, Station, theType, theHandle, theRect); { Turn this one on. }
- SetCtlValue(Pointer(TheHandle), 1);
- END;
-
- IF ItemHit IN [8,15,16,17] { Was it a check box? }
- THEN BEGIN
- GetDItem(Dptr, ItemHit, TheType, TheHandle, TheRect);
- TheValue := 1-GetCtlValue(Pointer(TheHandle)); { Find the value and invert it. }
- SetCtlValue(Pointer(TheHandle), TheValue);
- END;
- UNTIL ItemHit in [1,2];
-
- if itemHit = OK then begin { Have to get all the new values now! }
- GetDItem(Dptr, GSpeed, theType, theHandle, theRect); { Set up all the EditText boxes }
- GetIText(theHandle, TheString);
- GameSpeed := MinMax(TheString, 1, 99);
-
- GetDItem(Dptr, SRound, theType, theHandle, theRect);
- GetIText(theHandle, TheString);
- StartRound := MinMax(TheString, 1, 99);
-
- FOR i := 0 TO 2 DO BEGIN
- GetDItem(Dptr, MPB+i, theType, theHandle, theRect); { Text for points each missile is worth. }
- GetIText(theHandle, TheString);
- MPBase[i+1] := MinMax(TheString, -1000, 1000);
-
- GetDItem(Dptr, MPE+i, theType, theHandle, theRect); { Text for additional points each round }
- GetIText(theHandle, TheString);
- MPExtra[i+1] := MinMax(TheString, -1000, 1000);
-
- GetDItem(Dptr, MEX+i, theType, theHandle, theRect); { Check boxes for types of missiles }
- IF GetCtlValue(Pointer(TheHandle)) = 0
- THEN MExists[i+1] := False
- ELSE MExists[i+1] := True;
- END;
-
- FOR i := 0 to 2 DO BEGIN { radio buttons. }
- GetDItem(Dptr, MF2+i, theType, theHandle, theRect);
- IF GetCtlValue(Pointer(TheHandle)) = 1
- THEN MFlag2 := i;
- END;
-
- GetDItem(Dptr, MF1, theType, theHandle, theRect); { MFlag1. }
- IF GetCtlValue(Pointer(TheHandle)) = 0
- THEN MFlag1 := False
- ELSE MFlag1 := True;
- end; {if itemHit = OK}
-
- DisposDialog(DPtr);
- GetPort(savePort); {save whatever port was current}
- SetPort(MyWindow);
- InvalRect(ScreenRect); {force the entire screen, including frame, to be redrawn}
- SetPort(savePort);
- end; { of DoGameOptions }
-
- { %subtitle 'DoCommand - Does all the menu commands.' }
- PROCEDURE DoCommand (mResult: LongInt);
- VAR name: STR255;
- theMenu, theItem: INTEGER; { Menu and item numbers. }
- dummy: BOOLEAN;
- BEGIN
- theMenu := HiWord(mResult);
- theItem := LoWord(mResult);
- CASE theMenu OF
-
- appleMenu: { About Missile and Desk Accessories. }
- IF theItem = 1
- THEN AboutMissile
- ELSE BEGIN
- GetItem(myMenus[1],theItem,name);
- refNum := OpenDeskAcc(name);
- END;
-
- fileMenu: { There is currently only one option in this menu. }
- BEGIN
- doneFlag := TRUE;
- PauseFlag := False;
- esFlag := False;
- END;
-
- EditMenu: { Cut, copy, paste, and undo. }
- BEGIN
- dummy := SystemEdit(theItem-1); { Can't cut and paste in game window. }
- END; { of editMenu }
-
- GameMenu:
- BEGIN
- { SetPort(myWindow); }
- CASE theItem OF
- 1: PauseFlag := True; { pause game }
- 2: PauseFlag := False; { resume game }
- 3: ; { Empty line in menu. }
- 4: DoGameOptions;
- 5: BEGIN { New Game. }
- GameOver := True;
- EndDelay := 100;
- esFlag := False;
- PauseFlag := False;
- END;
- END; { of item case }
- END; { of editMenu }
-
- END; { of menu case }
- HiliteMenu(0);
-
- END; { of DoCommand }
-
- { %subtitle 'Routine to check for events.' }
- PROCEDURE CheckEvents;
- VAR MousePoint: Point;
- MouseCode: INTEGER;
- TheChar: CHAR;
- i: FIXED;
- fbrect: Rect; { Rectangle for drawing fireballs. }
- BEGIN
- REPEAT
- SystemTask;
-
- GetMouse(MousePoint);
- LocalToGlobal(MousePoint);
- MouseCode := FindWindow(MousePoint,whichWindow);
- IF FrontWindow = MyWindow { If my window is activated, set cursor: }
- THEN IF (WhichWindow = MyWindow) { If it's above my window, }
- AND (Mousecode <> inMenuBar) { but not the scroll bar, }
- AND (NOT PauseFlag) { the game is 'active', }
- AND (FrontWindow = MyWindow) { my window is in front, }
- AND (yLeft > 0) { and the user has missiles left, then: }
- THEN SetCursor(crosshairs) { Set the Missile Command cursor. }
- ELSE SetCursor(Arrow); { Otherwise, use an arrow. }
-
- WHILE GetNextEvent(everyEvent,myEvent) DO
- CASE myEvent.what OF
-
- mouseDown:
- BEGIN
- code := FindWindow(myEvent.where,whichWindow);
- CASE code OF
-
- inMenuBar:
- DoCommand(MenuSelect(myEvent.where));
-
- inSysWindow:
- SystemClick(myEvent,whichWindow);
-
- inDrag: ; { Can't drag game window - it's too hard to
- figure out collisions off-screen. }
-
- inGrow, inContent:
- BEGIN
- IF (whichWindow <> FrontWindow)
- AND (WhichWindow <> MyWindow) { Can't select MyWindow - must close other windows. }
- THEN SelectWindow(whichWindow)
- ELSE
- IF (NOT PauseFlag) { Can't make fireballs while paused. }
- AND (FrontWindow = MyWindow) { Game must be running }
- AND (yLeft > 0) { Make sure they have some missiles left. }
- THEN BEGIN
- GlobalToLocal(myEvent.where);
- IF myEvent.where.v > NukeHeight { If it's too low, }
- THEN myEvent.where.v := NukeHeight; { make it legal. }
- AllocFb(myEvent.where); { Put a fireball in the list. }
- yLeft := yLeft - 1; { They have less missiles now... }
- updScore; { let them know. }
- END;
- END;
-
- END; { of code case }
- END; { of mouseDown }
-
- keyDown: { No Autokey - don't want to repeat Option-N. }
- IF ((MyEvent.modifiers DIV 256)MOD 2<>0) { If command key was held down }
- THEN BEGIN
- TheChar := CHR(myEvent.message MOD 256);
- DoCommand(MenuKey(TheChar));
- END;
-
- updateEvt:
- BEGIN
- SetPort(myWindow);
- BeginUpdate(myWindow);
-
- IF Playing THEN BEGIN
- FOR i:= 1 TO nCities DO
- IF cities[i]
- THEN BEGIN
- DrawCity(i);
- END;
- RandSeed := TickCount; { Randomize after drawing cities. }
-
- FOR i:= 1 TO maxMs DO
- IF missiles[i].mode = msActive
- THEN BEGIN
- PenSize(mWidth, mWidth);
- PenPat(Gray);
- MoveTo(missiles[i].start.h, missiles[i].start.v);
- LineTo(missiles[i].pos.h DIV 16, missiles[i].pos.v DIV 16);
- END;
-
- FOR i:= 1 TO maxFb DO
- IF fbs[i].mode <> fbIdle
- THEN BEGIN
- fbRect := fbs[i].bounds;
- insetRect(fbRect, 30-2*fbs[i].size, 30-2*fbs[i].size);
- PenMode(PatCopy);
- FillOval(fbRect, Black);
- END;
- END;
-
- BottomLine;
-
- EndUpdate(myWindow);
- END; { of updateEvt }
-
- END; { of event case }
-
- UNTIL (FrontWindow = MyWindow) { If another window has been selected, }
- AND NOT PauseFlag; { don't do anything except process events }
- { until game window is re-selected. }
- END; { of CheckEvents }
-
- { %subtitle 'Print the GAME OVER message.' }
- PROCEDURE EndScreen;
- VAR aRect: Rect;
- i: INTEGER;
- GameOffset, OverOffset: INTEGER;
- Center: Point;
- BEGIN
- TextSize(72);
- TextMode(srcBic);
- PenMode(patOr);
- PenPat(Black);
- PenSize(5,5);
-
- GameOffset := StringWidth('GAME') DIV 2;
- OverOffset := StringWidth('OVER') DIV 2;
- Center.v := FieldHeight DIV 2;
- Center.h := FieldWidth DIV 2;
-
- SetRect(aRect, Center.h, Center.v, Center.h, Center.v);
- FOR i := 1 TO 30 DO BEGIN
- CheckEvents;
-
- InsetRect(aRect,-5,-5);
- FrameOval(aRect);
- TextSize(72);
- TextMode(srcBic);
- Centre('GAME', Center.v - 12);
- Centre('OVER', Center.v + 60);
- END;
-
- PenMode(patBic);
- FOR i := 1 TO 30 DO BEGIN
- CheckEvents;
-
- FrameOval(aRect);
- InsetRect(aRect,5,5);
- END;
-
- END; { of EndScreen }
-
- { %subtitle 'Play a single game.' }
- PROCEDURE PlayGame;
- VAR i: INTEGER;
- s: Str255;
- msPoint: Point;
- msCity, msKind: INTEGER;
- rMissiles: INTEGER; { "round missiles" - number to set eLeft to each round. }
- yMissiles: INTEGER; { "your Missiles" - similar to rMissiles. }
- RoundOver: BOOLEAN;
- aString: Str255;
- Points: INTEGER;
-
- PROCEDURE InitRound;
- VAR
- i: INTEGER;
- BEGIN
- RoundOver := False;
- endDelay := 0;
- Playing := True;
-
- DrawStuff; { Redraw screen. }
-
- FOR i := 1 TO maxfb DO
- fbs[i].mode := fbIdle;
-
- FOR i := 1 TO maxms DO
- missiles[i].mode := msIdle;
-
- FOR i := 1 TO 3 DO
- MPoints[i] := MPBase[i] + MPExtra[i] * RoundNumber;
-
- FOR i := 1 TO nCities DO
- cities2[i] := cities[i];
-
- nMissiles := 0;
-
- MirvRate := 0;
- mirvHeight := FieldHeight DIV 4;
- mirvNasty := 30;
- msSpeed := 60;
- IF RoundNumber >2 THEN MirvRate := 10;
- IF RoundNumber >4 THEN msSpeed := 80;
- IF RoundNumber >6 THEN MirvRate := 20;
- IF RoundNumber >8 THEN MirvNasty := 50;
- IF RoundNumber >10 THEN MirvHeight := FieldHeight DIV 3;
- IF RoundNumber >12 THEN msSpeed := 90;
- IF RoundNumber >14 THEN MirvRate := 30;
- IF RoundNumber >19 THEN msSpeed := 100;
-
- msRate := 5 + RoundNumber;
- rMissiles := (RoundNumber*RoundNumber)DIV 6 + RoundNumber + 6; { Compute # of enemy missiles }
- yMissiles := rMissiles + RoundNumber; { Adjust yMissiles accordingly. }
- eLeft := rMissiles;
- yLeft := yMissiles;
- RoundNumber := RoundNumber + 1;
- IF (RoundNumber MOD 5) = 0
- THEN bCities := bCities + 1;
-
- BottomLine;
- FlushEvents(everyEvent,0); { Ignore unprocessed events from previous round. }
- END;
-
- PROCEDURE EndBonus;
- VAR
- i: INTEGER;
- BEGIN;
- ClearScreen;
- BottomLine;
-
- TextSize(24);
- TextMode(srcCopy);
-
- aString := 'End of round ';
- aString[15] := Chr(48+(RoundNumber Mod 10));
- IF RoundNumber>9
- THEN aString[14] := Chr(48+(RoundNumber DIV 10));
-
- IF CitiesLeft>0
- THEN BEGIN { give bonus points for cities }
- Centre(aString, 100);
- Centre('Bonus:', 130);
- Points := 0;
- FOR i:= 1 TO nCities DO
- IF (cities[i] AND NOT DoneFlag) THEN BEGIN
- LastTick := TickCount;
-
- DrawCity(i);
- Points := Points + RoundNumber*20;
- Score := Score + RoundNumber*20;
- TextSize(24);
- NumtoString(Points, S);
- Centre(S, 160);
- updScore;
-
- REPEAT
- CheckEvents;
- UNTIL (TickCount >= LastTick + 30) OR DoneFlag;
- END
- END; { of bonus for cities. }
- IF (bCities > 0) AND (CitiesLeft < 6)
- THEN BEGIN { Give a bonus city. }
- LastTick := TickCount;
- TextSize(24);
- Centre('* Bonus City *', 190);
- CitiesLeft := CitiesLeft + 1;
- bCities := bCities - 1;
- REPEAT
- i := Rnd(6)
- UNTIL (NOT Cities[i]);
- Cities[i] := true;
- REPEAT
- CheckEvents;
- UNTIL (TickCount >= LastTick + 60) OR DoneFlag;
- END { of bonus city routine. }
- END; { of EndBonus }
-
- BEGIN
- RoundNumber := StartRound; { Start out at this round. }
- Score := 0;
- eDestroyed := 0;
-
- FOR i := 1 TO nCities DO
- cities[i] := true;
- citiesLeft := nCities;
- bCities := 0;
-
- NukeHeight := FieldHeight - CityHeight - (BuildHeight DIV 2) - fbRad*fbRadRate;
- endv := FieldHeight - CityHeight - (BuildHeight DIV 2);
-
- GameOver := False;
- esFlag := True;
- lastTick := TickCount;
-
- REPEAT { Repeat loop for playing rounds. }
- InitRound;
-
- REPEAT { Repeat loop for animating objects in game. }
- CheckEvents;
-
- IF TickCount >= lastTick + gameSpeed { If enough time has elapsed since the
- last update, update objects on screen. }
- THEN BEGIN
- lastTick := TickCount;
- IF (eLeft <= 0) AND (nMissiles = 0) THEN RoundOver := True;
-
- IF RoundOver OR GameOver
- THEN endDelay := endDelay + 1
- ELSE
- IF (rnd(100) < msRate) AND (eLeft > 0)
- THEN BEGIN { Launch an enemy missile every now and then. }
- eLeft := eLeft - 1;
- msPoint.v := 0;
- msPoint.h := Rnd(FieldWidth - 4);
- REPEAT
- msCity := Rnd(nCities); { Pick a city. }
- UNTIL ((Rnd(3) = 1) AND mFlag1)
- OR cities2[msCity]; { Try again for most missiles if city was destroyed. }
-
- msKind := 0;
- IF MExists[msNormal]
- THEN msKind := msNormal;
- IF (rnd(100) <= MirvRate) AND MExists[msMirv]
- THEN msKind := msMirv;
- IF msKind = 0 THEN msKind := msNormal;
-
- AllocMs(msPoint, msCity, msKind);
- END;
-
- AdvanFb; { Advance state of fireballs. }
- AdvanMs; { Advance position of missiles. }
- END;
-
- UNTIL ((GameOver OR RoundOver) AND (endDelay > 30)) OR doneFlag;
- { End of loop to move objects on screen. }
-
- Playing := False;
- IF esFlag AND (CitiesLeft+bCities>0) AND NOT DoneFlag
- THEN EndBonus;
-
- UNTIL GameOver OR DoneFlag; { End of loop to play rounds. }
-
- IF Score > HighScore
- THEN HighScore := Score;
-
- IF esFlag
- THEN EndScreen;
-
- END; { of PlayGame }
-
- { %subtitle 'Main program.' }
- BEGIN { main program }
- SetUp;
-
- REPEAT
- PlayGame;
- UNTIL doneFlag;
- END.
-
- *
- ----------- Cut here --- Missile.r (resource source file) ------------
-
-
- * Missiler -- resource file for Missile
- * (Robert Munafo @ Dartmouth College)
-
- RJUNK27.RSRC
-
- * These are the menus for the program -
- * Menu ID
- * Menu title
- * Menu Item
- * Menu Item, etc.
- Type MENU
- ,1
- @
- About Missile
- (-
-
- ,256
- File
- Quit
-
- ,257
- Edit
- Undo/Z
- (-
- Cut/X
- Copy/C
- Paste/V
- Clear
-
- ,258
- Game
- Pause/S
- Resume/Q
- (-
- Game Options/O
- New Game/N
-
- * String information
- * ID
- * string
- Type STR
- ,300
- Missile Command by Robert P. Munafo
-
- ,350
- Vers 2.3 August 18,1984
-
- * Dialog Box for About Missile
- * ID
- * display rectangle
- * visible, standard box, no close box, RefCon
- * ID of content list
- Type DLOG
- ,450
- 100 110 190 402
- Visible 1 NoGoAway 0
- 500
-
- * Dialog Item List for About Missile
- * ID of list
- * number of items in list
- * a button that can be hit
- * display rectangle (coordinates local to box)
- * title of button
- Type DITL
- ,500
- 3
- BtnItem Enabled
- 65 106 85 186
- OK
-
- StatText Disabled
- 10 10 30 300
-
- StatText Disabled
- 35 10 55 300
-
- * Dialog box for Game Options
- Type DLOG
- ,451
- 40 40 302 472
- Visible 1 NoGoAway 0
- 501
-
- * Dialog item list for Game Options
- * Lots and lots of little options for people to play around with.
- * Run the program if you want to see what the dialog box looks like...
- Type DITL
- ,501
- 29
- BtnItem Enabled
- 200 320 220 400
- OK
-
- BtnItem Enabled
- 230 320 250 400
- Cancel
-
- StatText Disabled
- 8 130 24 400
- Missile Command Options
-
- StatText Disabled
- 40 4 56 124
- Animation delay
-
- EditText Enabled
- 40 140 56 170
- num
-
- StatText Disabled
- 40 200 56 350
- Start off with round #
-
- EditText Enabled
- 40 360 56 380
- num
-
- ChkItem Enabled
- 64 4 80 400
- Missiles aim for dead cities
-
- StatText Disabled
- 88 4 104 400
- Missiles blow up when destroyed:
-
- RadioItem Enabled
- 104 4 120 150
- Always
-
- RadioItem Enabled
- 104 160 120 400
- Never
-
- RadioItem Enabled
- 120 4 136 400
- Less often with each round
-
- StatText disabled
- 144 4 160 100
- Type:
-
- StatText disabled
- 144 160 160 400
- Points for destroying:
-
- ChkItem enabled
- 176 4 192 140
- Missiles
-
- ChkItem enabled
- 196 4 212 140
- MIRVs
-
- ChkItem disabled
- 216 4 232 140
- Smart bombs
-
- EditText enabled
- 176 160 192 190
- num
-
- EditText enabled
- 196 160 212 190
- num
-
- EditText enabled
- 216 160 232 190
- num
-
- StatText disabled
- 176 200 192 208
- plus
-
- StatText disabled
- 196 200 212 208
- plus
-
- StatText disabled
- 216 200 232 208
- plus
-
- EditText enabled
- 176 215 192 245
- num
-
- EditText enabled
- 196 215 212 245
- num
-
- EditText enabled
- 216 215 232 245
- num
-
- StatText disabled
- 176 255 192 300
- x round
-
- StatText disabled
- 196 255 212 300
- x round
-
- StatText disabled
- 216 255 232 300
- x round
-
- * Crosshairs cursor. It has no mask, so it will look
- * like a white crosshairs on a black background.
- * ID
- * hex data
- * hex mask
- * hotspot (v,h)
- Type CURS
- ,256
- 0180018001800180018001800180FFFFFFFF0180018001800180018001800180
- 0000000000000000000000000000000000000000000000000000000000000000
- 0008 0008
-
- * Pattern of closely spaced vertical stripes, for drawing
- * the cities.
- Type PAT
- ,256
- 5555555555555555
-
- * This is the window the game graphics are drawn in.
- * It is so big that all of its edges are off-screen -
- * this makes it appear that the program is drawing on
- * the entire screen without using a window.
- Type WIND
- ,256
- Missile Command
- 20 0 342 512
- Visible NoGoAway
- 0
- 0
-
- * The Finder must be able to find this string -
- * it identifies the version number of the program.
- Type RJUN = STR
- ,0
- Game Vers 2.3 August 18,1984
-
- * Part of the "Finder Info" :
- * Resource ID (purgable)
- * Hex for "APPL"
- * Local icon ID
- * name of file that must be transferred along with
- * the application when it is copied ("00" means none)
- Type FREF = HEXA
- ,128(32)
- 4150504C
- 0000
- 00
-
- * Special icon and mask for application.
- * The mask is a big solid rectangle to make it easy
- * to select in the Finder.
- Type ICN# = HEXA
- ,128 (32)
- 00000000
- 00000000
- 00000000
- 00000000
- 00000000
- 00000000
- 01000100
- 01000200
- 00800400
- 00800800
- 00401000
- 00402000
- 00204000
- 00008380
- 000107C0
- 000207C0
- 000467C0
- 0008F380
- 0010F000
- 00206000
- 00400000
- 00800000
- 01000000
- 00000000
- 00000000
- 00000000
- 20202020
- 28282828
- 3A3A3A3A
- 7E7E7E7E
- 00000000
- 00000000
- 00000000
- 00000000
- 00000000
- 00000000
- 00000000
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- FFFFFFFF
- 00000000
-
-
- * Bundle data for Missile:
- * Bundle ID
- * the owner ("RJUN" in hex), and ID of version data
- * # of types in the bundle (less one) - in this case,
- * there are two types.
- * "ICN#" in hex, and # of icons less one.
- * Local ID 0 maps to global ID 256.
- * "FREF" in hex, and # of FREF's less one.
- * Local ID 0 maps to global ID 256.
- * (note that if the game created any documents, this
- * bundle would need at least two icons and two FREF's.)
- Type BNDL = HEXA
- ,128
- 524A554E 0000
- 0001
- 49434E23 0000
- 0000 0080
- 46524546 0000
- 0000 0080
-
- * The code - my Exec file always saves the executable
- * code with this name.
- Type CODE
- RJUNK27L,0
-
- *
- ------------ Cut Here --- End of Missile Command Source -------------
- --
- mrob's .sig #4 | '^`^` T_, .-`
- collect all 5! | Internet: mrob@world.std.com "r"-, .---F
-